package Underworld_Survival;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static Underworld_Survival.Game.gameOutput;
import static Underworld_Survival.GameOutput.MsgType;
import static Underworld_Survival.GameOutput.Template.*;

// 定义所有可修改的属性类型
enum AttributeType {
    // 基础属性（只能增加）
    BASE_MAXHP("血量"),
    BASE_MAXAGI("能量"),
    BASE_STR("基础力量"),
    BASE_DEF("基础防御"),
    BASE_EP("基础速度"),
    // 加成属性（可增减）
    BONUS_MAXHP("血量"),
    BONUS_MAXAGI("能量"),
    BONUS_STR("力量"),
    BONUS_DEF("防御"),
    BONUS_EP("速度"),
    // 特殊属性
    BASE_CRITRATE("基础暴击率"),
    BONUS_CRITRATE("暴击率"),
    BASE_CRITMULTIPLIER("基础暴击效果"),
    BONUS_CRITMULTIPLIER("暴击效果");
    private final String description;
    AttributeType(String description){
        this.description=description;
    }
    public String getDescription(){
        return description;
    }

}

abstract class Role {
    protected String name;//名字
    protected int currentHP;//当前生命值
    protected int baseMaxHP;//基础生命值上限
    protected int bonusMaxHP=0;//加成生命值上限
    protected int totalMaxHP;//总生命值上限
    protected int baseStr;//基础力量
    protected int bonusStr=0;//加成力量
    protected int totalStr;//总力量
    protected int baseDef;//基础防御
    protected int bonusDef=0;//加成防御
    protected int totalDef;//总防御
    protected int baseEP;//基础速度
    protected int bonusEP=0;//加成速度
    protected int totalEP;//总速度
    protected float baseCritRate=0.2f; // 基础暴击率为0.2
    protected float bonusCritRate=0; // 加成暴击率
    protected float totalCritRate; // 总暴击率
    protected float baseCritMultiplier=1.5f; // 基础暴击倍率（默认1.5）
    protected float bonusCritMultiplier=0; // 加成暴击倍率
    protected float totalCritMultiplier; // 总暴击倍率
    protected EffectManager effectManager;//每一个单独的个体都有一个数据管理器
    protected List<Buff> buff;//临时buff状态(可能是多种状态叠加，所以用列表)
    protected Ability ability;//能力(技能)
    protected WeaponSlot weaponSlot;//武器槽
    protected ArmorSlot armorSlot;//防具槽
    protected ShoeSlot shoeSlot;//鞋子槽


    public Role() {}
    //角色的初始化，默认满血，只有基础力量，防御，速度，暴击，暴击效果，没有武器，防具，鞋子
    public Role(String name,int baseMaxHP, int baseStr, int baseDef, int baseEP){
        this.name=name;
        this.currentHP=baseMaxHP;
        this.totalMaxHP=baseMaxHP;
        this.totalStr=baseStr;
        this.totalDef=baseDef;
        this.totalEP=baseEP;
        this.totalCritRate=baseCritRate;
        this.totalCritMultiplier=baseCritMultiplier;
        this.baseMaxHP=baseMaxHP;
        this.baseStr=baseStr;
        this.baseDef=baseDef;
        this.baseEP=baseEP;
        effectManager=new EffectManager();
        buff=new ArrayList<>();
        ability=new Ability();
        weaponSlot=new WeaponSlot();
        armorSlot=new ArmorSlot();
        shoeSlot=new ShoeSlot();
    }

    // 获取所有已装备的物品
    public List<Equipment> getEquipments() {
        return Stream.of(
                        weaponSlot.getEquippedItem(),
                        armorSlot.getEquippedItem(),
                        shoeSlot.getEquippedItem()
                )
                .filter(Objects::nonNull)  // 过滤空槽
                .collect(Collectors.toList());
    }
    //

    public void equipWithEquipment(Equipment equipment){
        if(equipment instanceof Weapon){
            if(weaponSlot.hasWeapon()){
                removeEquipment(weaponSlot.getEquippedItem());
            }
            ((Weapon)equipment).equip(this);//武器处于装备状态，触发武器装备的效果
            weaponSlot.equip(((Weapon)equipment));//武器槽装上这把武器
            //背包里面移除这把武器
        }else if(equipment instanceof Armor){
            if(armorSlot.hasArmor()){
                removeEquipment(armorSlot.getEquippedItem());
            }
            ((Armor)equipment).equip(this);//防具处于装备状态，触发防具装备的效果
            armorSlot.equip(((Armor)equipment));//防具槽装上这把防具
            //背包里面移除这把防具
        }else if(equipment instanceof Shoe){
            if(shoeSlot.hasShoe()){
                removeEquipment(shoeSlot.getEquippedItem());
            }
            ((Shoe)equipment).equip(this);//鞋子处于装备状态，触发鞋子装备的效果
            shoeSlot.equip(((Shoe)equipment));//鞋子槽装上这把防具
            //背包里面移除这双鞋子
        }else{
            throw new IllegalStateException("装备非法类型的装备！");
        }
    }
    public void removeEquipment(Equipment equipment){
        if(equipment instanceof Weapon){
            ((Weapon)equipment).unequip(this);//将武器装备的效果移除
            weaponSlot.unequip();//武器槽卸下这把武器
            //背包里获得这把武器
        }else if(equipment instanceof Armor){
            ((Armor)equipment).unequip(this);//将防具装备的效果移除
            armorSlot.unequip();//防具槽卸下这把武器
            //背包里获得这把防具
        }else if(equipment instanceof Shoe){
            ((Shoe)equipment).unequip(this);//将鞋子装备的效果移除
            shoeSlot.unequip();//鞋子槽卸下这把武器
            //背包里获得这把鞋子
        }else{
            throw new IllegalStateException("卸除非法类型的装备！");
        }
    }


    //buff面触发了之后buff持续回合数要减一，持续回合数为0的buff，移除该buff）
    public void updateBuff(Buff buff,Role role,BattleManager battleCtx){
        buff.updateDuration();
        if (buff.isExpired()) {
            gameOutput.print(MsgType.STATUS, buff.getName() + "效果消失   ");
            if (role != null) buff.onExpire(this);
            else buff.onExpire(battleCtx);
        }
    }
    // 事件中触发特定条件的Buff效果,并更新buff列表
    public void triggerBuffsInStage(BuffTriggerCondition condition) {
        Iterator<Buff> iterator = buff.iterator();
        while (iterator.hasNext()) {
            Buff currentBuff = iterator.next();
            if (currentBuff.getTriggerConditions().contains(condition)) {
                System.out.println(currentBuff.getName() + "buff触发");
                currentBuff.onTrigger(this);//运用buff效果
                this.updateBuff(currentBuff, this, null);
                if (currentBuff.isExpired()) {
                    iterator.remove();
                }
            }
        }
    }
    // 战斗中触发特定条件的Buff效果,并更新buff列表
    public void triggerBuffsInBattle(BuffTriggerCondition condition, BattleManager battleCtx) {

        Iterator<Buff> iterator = buff.iterator();
        while (iterator.hasNext()) {
            Buff currentBuff = iterator.next();
            if (currentBuff.getTriggerConditions().contains(condition)) {
                System.out.println(currentBuff.getName() + "buff触发");
                currentBuff.onTrigger(battleCtx);//运用buff效果
                this.updateBuff(currentBuff, null, battleCtx);
                if (currentBuff.isExpired()) {
                    iterator.remove();
                }
            }
        }

    }
    //添加buff
    public void addBuff(Buff newBuff) {
        Optional<Buff> existing = buff.stream()
                .filter(b -> b.getName().equals(newBuff.getName()))
                .findFirst();

        if (existing.isPresent()) {//存在相同名称buff
            existing.get().refresh(); // 刷新已有 Buff
            if(this instanceof Player){
                gameOutput.println(MsgType.STATUS,pRefreshBuff,newBuff.getName(),
                        newBuff.getInitialDuration());
            }else{
                gameOutput.println(MsgType.STATUS,mRefreshBuff,name,newBuff.getName(),
                        newBuff.getInitialDuration());
            }
        } else {
            buff.add(newBuff);
            if(this instanceof Player){
                gameOutput.println(MsgType.STATUS,pGetBuff, newBuff.getName(),
                        newBuff.getInitialDuration(),newBuff.getEffectIntroduction());
            }else{
                gameOutput.println(MsgType.STATUS,mGetBuff,name,newBuff.getName(),
                        newBuff.getInitialDuration(),newBuff.getEffectIntroduction());
            }
        }
        if(newBuff.getTriggerConditions().contains(BuffTriggerCondition.ON_APPLY)){
            newBuff.onApply(this);
        }
    }
    //显示buff列表
    public void showBuff(){
        if(!buff.isEmpty()){
            gameOutput.print(MsgType.STATUS,"Buff：");
            for(int i=0;i<buff.size();i++){
                gameOutput.print(MsgType.STATUS,buff.get(i).getName()+buff.get(i).getRemainingDuration()+"   ");
            }
            System.out.println();
        }
    }
    //移除buff列表的Debuff
    public void removeDebuff(){
        Iterator<Buff> iterator=buff.iterator();
        while(iterator.hasNext()){
            Buff buff=iterator.next();
            if(buff.isIsDebuff()&&!buff.getName().equals("【诅咒】")){
                gameOutput.println(MsgType.STATUS,buff.getName()+"消失 ");
                buff.onExpire(this);//buff消失时的效果触发
                iterator.remove();
            }
        }
        System.out.println();
    }

    public void updateAttribute(){
        totalMaxHP=bonusMaxHP+baseMaxHP;
        totalStr=bonusStr+baseStr;
        totalDef=bonusDef+baseDef;
        totalEP=bonusEP+baseEP;
        totalCritRate=baseCritRate+bonusCritRate;
        totalCritMultiplier=baseCritMultiplier+bonusCritMultiplier;
    }
    public boolean isAlive(){return currentHP>0;}

    //修改各种属性，不包括当前血量和当前能量，并且更新属性
    public void modifyAttributes(Map<AttributeType, Float> modifiers,boolean isPrint) {
        modifiers.forEach((type, value) -> {
            switch (type) {
                // 基础属性（只能增加）
                case BASE_MAXHP:
                    this.baseMaxHP += Math.max(0, value.intValue());//value.intValue()由于value是一个浮点型，这了取值整数部分
                    break;
                case BASE_STR:
                    this.baseStr += Math.max(0, value.intValue());//value.intValue()由于value是一个浮点型，这了取值整数部分
                    break;
                case BASE_DEF:
                    this.baseDef += Math.max(0, value.intValue());
                    break;
                case BASE_EP:
                    this.baseEP += Math.max(0, value.intValue());
                    break;
                // 加成属性（可正可负）
                case BONUS_MAXHP:
                    this.bonusMaxHP += value.intValue();
                    break;
                case BONUS_STR:
                    this.bonusStr += value.intValue();
                    break;
                case BONUS_DEF:
                    this.bonusDef += value.intValue();
                    break;
                case BONUS_EP:
                    this.bonusEP += value.intValue();
                    break;
                // 特殊属性处理
                case BASE_CRITRATE:
                    this.baseCritRate = clamp(value + this.baseCritRate, 0f, 1f);//暴击率的增加值最小0，最大1
                    break;
                case BONUS_CRITRATE:
                    this.bonusCritRate = clamp(value + this.bonusCritRate, 0f, 1f);
                    break;
                case BASE_CRITMULTIPLIER:
                    this.baseCritMultiplier = clamp(value + this.baseCritMultiplier, 0f, 3f);
                    break;
                case BONUS_CRITMULTIPLIER:
                    this.bonusCritMultiplier = clamp(value + this.bonusCritMultiplier, 0f, 3f);
                    break;
            }
            if(isPrint) {
                if (value < 0) {
                    gameOutput.print(MsgType.DECREASE, "%s%s降低%.2f   ", name, type.getDescription(), -value);
                } else {
                    gameOutput.print(MsgType.INCREASE, "%s%s提升%.2f   ", name, type.getDescription(), value);
                }
            }
        });
        updateAttribute();//增加完后更新属性
    }

    // 数值范围限制工具方法（增加值只能在min和max之间）
    protected float clamp(float value, float min, float max) {
        return Math.max(min, Math.min(max, value));
    }

    //受伤，回血
    public void refillHP(int value){
        if(currentHP+value>totalMaxHP){
            currentHP=totalMaxHP;
        }else{
            currentHP+=value;
        }
        gameOutput.println(MsgType.RECOVER,mRefillHP,name,value,currentHP,totalMaxHP);
    }
    public void reduceHP(int value){
        if(currentHP<value){
            currentHP=0;
        }else{
            currentHP-=value;
        }
    }

    //基础属性的getter,setter
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public int getCurrentHP() {return currentHP;}
    public void setCurrentHP(int currentHP) {this.currentHP = currentHP;}
    public int getBaseMaxHP() {return baseMaxHP;}
    public void setBaseMaxHP(int baseMaxHP) {this.baseMaxHP = baseMaxHP;}
    public int getBonusMaxHP() {return bonusMaxHP;}
    public void setBonusMaxHP(int bonusMaxHP) {this.bonusMaxHP = bonusMaxHP;}
    public int getTotalMaxHP() {return totalMaxHP;}
    public void setTotalMaxHP(int totalMaxHP) {this.totalMaxHP = totalMaxHP;}
    public int getBaseStr() {return baseStr;}
    public void setBaseStr(int baseStr) {this.baseStr = baseStr;}
    public int getBonusStr() {return bonusStr;}
    public void setBonusStr(int bonusStr) {this.bonusStr = bonusStr;}
    public int getTotalStr() {return totalStr;}
    public void setTotalStr(int totalStr) {this.totalStr = totalStr;}
    public int getBaseDef() {return baseDef;}
    public void setBaseDef(int baseDef) {this.baseDef = baseDef;}
    public int getBonusDef() {return bonusDef;}
    public void setBonusDef(int bonusDef) {this.bonusDef = bonusDef;}
    public int getTotalDef() {return totalDef;}
    public void setTotalDef(int totalDef) {this.totalDef = totalDef;}
    public int getBaseEP() {return baseEP;}
    public void setBaseEP(int baseEP) {this.baseEP = baseEP;}
    public int getBonusEP() {return bonusEP;}
    public void setBonusEP(int bonusEP) {this.bonusEP = bonusEP;}
    public int getTotalEP() {return totalEP;}
    public void setTotalEP(int totalEP) {this.totalEP = totalEP;}
    public float getBaseCritRate() {return baseCritRate;}
    public void setBaseCritRate(float baseCritRate) {this.baseCritRate = baseCritRate;}
    public float getBonusCritRate(){return bonusCritRate;}
    public void setBonusCritRate(float bonusCritRate){this.bonusCritRate=bonusCritRate;}
    public float getTotalCritRate() {return totalCritRate;}
    public void setTotalCritRate(float totalCritRate) {this.totalCritRate = totalCritRate;}
    public float getBaseCritMultiplier() {return baseCritMultiplier;}
    public void setBaseCritMultiplier(float baseCritMultiplier) {this.baseCritMultiplier = baseCritMultiplier;}
    public float getBonusCritMultiplier(){return bonusCritMultiplier;}
    public void setBonusCritMultiplier(float bonusCritMultiplier){this.bonusCritMultiplier=bonusCritMultiplier;}
    public float getTotalCritMultiplier() {return totalCritMultiplier;}
    public void setTotalCritMultiplier(float totalCritMultiplier) {this.totalCritMultiplier = totalCritMultiplier;}
    public EffectManager getEffectManager(){
        return effectManager;
   }
    public void setEffectManager(EffectManager manager){
        this.effectManager=manager;
   }
    public List<Buff> getBuff() {return buff;}
    public void setBuff(List<Buff> buff) {this.buff = buff;}
    public Ability getAbility() {return ability;}
    public void setAbility(Ability ability) {this.ability = ability;}
    public WeaponSlot getWeaponSlot() {return weaponSlot;}
    public void setWeaponSlot(WeaponSlot weaponSlot) {this.weaponSlot = weaponSlot;}
    public ArmorSlot getArmorSlot() {return armorSlot;}
    public void setArmorSlot(ArmorSlot armorSlot) {this.armorSlot = armorSlot;}
    public ShoeSlot getShoeSlot() {return shoeSlot;}
    public void setShoeSlot(ShoeSlot shoeSlot) {this.shoeSlot = shoeSlot;}


}
